package liumeiya.rbac.view;

import liumeiya.rbac.Main;
import liumeiya.rbac.domain.dto.DeptDto;
import liumeiya.rbac.domain.entity.Dept;
import liumeiya.rbac.domain.vo.DeptVo;
import liumeiya.rbac.domain.vo.Result;
import liumeiya.rbac.service.DeptService;

public class DeptView {
    /**
     * 输出部门管理菜单
     */
    public static void printMenu(){
        String menu = """
                ------------------
                     部门管理
               ------------------
               |   0...返回上级   |
               |   1...部门列表   |
               |   2...新建部门   |
               |   3...更新部门   |
               |   4...删除部门   |
               -------------------
               请输入选项：""";
        System.out.print(menu);
    }
    
    public static void printError(String message) {
        System.out.println("\033[31m" + message +"\033[0m");
    }

    /**
     *  视图对象缓存数组
     */
    public static DeptVo[] cache;

    public static void show(){
        String menuChoice;
        do {
            printMenu();
            menuChoice = MainView.input.nextLine();
            switch (menuChoice) {
                case "0" -> printError("已返回上一级菜单");
                case "1" -> list();
                case "2" -> create();
                case "3" -> update();
                case "4" -> delete();
                default -> printError("输入非法，请输入正确的菜单编号！");
            }
        } while (!"0".equals(menuChoice));
    }

    /**
     * 列出所有部门的信息。
     * <p>
     * 本方法调用服务层获取所有部门数据， 并将其存储在缓存中。 然后。输出所有部门的ID、 名称和电话，
     * 以表格形式显示在控制台中， 供用户查看。
     * </p>
     */
    public static void list() {
        Result result = DeptService.list();

        cache = (DeptVo[]) result.data;

        printError("ID\t部门名称\t部门电话");

        for (DeptVo dept : cache) {
            if (dept != null) {
                System.out.printf("%d\t%s\t%s\n", dept.id, dept.name,dept.phone);
            }
        }
    }

    /**
     * 创建一个新的部门。
     * <p>
     * 本方法会提示用户输入部门的名称和电话， 并将这些信息封装到一个 ‘DeptDto’ 对象中。
     * 然后调用服务层的创建方法， 若创建成功， 则输出成功信息并列出当前所有部门; 若失败，则输出错误信息。
     * </p>
     */
    public static void create() {
        //提示用户输入部门名称
        System.out.print("请输入部门名称：");

        String name = MainView.input.nextLine();//获取用户输入的部门名称

        //提示用户输入部门电话
        System.out.print("请输入部门电话");
        String phone = MainView.input.nextLine();//获取用户输入的部门电话

        //将用户输入的部门名称和电话封装到DeptDto对象中
        DeptDto dto = new DeptDto(name, phone);

        //调用服务层的创建方法， 创建新的部门
        Result result = DeptService.create(dto);

        // 如果创建操作失败， 输出错误信息
        if (!result.success) {
            System.err.println(result.message);
            return; //结束方法执行
        }

        //创建成功，输出成功信息
        printError(result.message);

        // 列出当前所有部门信息
        list();
    }

    /**
     * 更新指定部门的信息。
     * <p>
     * 本方法会提示用户输入部门的ID， 并验证该ID 是否有效。 然后从缓存中查找对应部门数据
     * 如果未找到部门，提示用户。如果找到部门， 用户可以选择修改部门名称和电话，若用户没有修改，则保持原值。
     * 更新成功后， 会返回更新结果并列出当前部门列表。
     * </p>
     */
    public static void update() {
        DeptVo dept = getCacheById();

        if(dept == null) {
            return;
        }
        // 提示用户输入新的部门名称， 按回车表示不修改
        System.out.print("请输入部门名称，直接按回车表示不修改：");
        String name = MainView.input.nextLine();
        // 如果用户没有输入新名称， 保持原名称
        name = "".equals(name) ? dept.name : name;

        // 提示用户输入新的部门电话， 按回车表示不修改
        System.out.print("请输入部门电话，直接按回车表示不修改：");
        String phone = MainView.input.nextLine();
        // 如果用户没有输入新电话， 保持原电话
        phone = "".equals(phone) ? dept.phone : phone;

        // 创建新的 DeptDto 对象， 用于更新部门信息
        DeptDto dto = new DeptDto(name, phone);

        // 调用服务层更新部门信息
        Result result = DeptService.update(dto, dept.id);

        // 如果更新失败， 显示错误信息
        if (!result.success) {
            System.err.println(result.message);
            return;
        }

        // 更新成功，显示成功消息并列出部门信息
        printError(result.message);
        list(); // 列出更新后的部门列表
    }

    /**
     * 删除指定部门信息
     * <p>
     * 本方法会提示用户输入部门的 ID， 并验证该 ID 是否有效。然后从缓存中查找对应部门数据，
     * 如果未找到部门，则提示用户。 若找到部门，用户需确认是否删除该部门，确认后将删除该部门。
     * 如果删除失败， 则提示失败信息； 删除成功后， 重新列出部门信息。
     * </p>
     */
    public static void delete() {
        DeptVo dept = getCacheById();

        if(dept == null) {
            return;
        }

        // 提示用户确认是否删除
        System.out.print("请输入'Y'确认删除， 输入其他取消删除：");
        String confirm = MainView.input.nextLine();

        // 如果用户输入的不是'Y'或'y’， 则取消删除
        if (!"Y".equalsIgnoreCase(confirm)) {
            System.out.println("您已取消删除");
            return;
        }

        // 调用服务层进行删除操作
        Result result = DeptService.delete(dept.id);

        // 如果删除操作失败，提示错误信息
        if (!result.success) {
            printError(result.message);
            return;
        }

        // 删除成功，输出成功信息并列出当前部门列表
        System.out.println(result.message);
        list();
    }
    public static DeptVo getCacheById() {
        // 提示用户输入部门ID
        System.out.print("请输入ID， ID必须是大于0的整数：");

        // 验证用户输入的ID是否为整数
        if (!MainView.input.hasNextInt()) {
            // 清除无效输入
            MainView.input.nextLine();
            printError("ID必须为整数，请输入整数值");
            return null;
        }

        // 获取用户输入的ID
        int id = MainView.input.nextInt();
        // 清除输入缓存中的换行符
        MainView.input.nextLine();

        // 验证ID 是否大于0
        if (id < 1) {
            printError("ID必须大于0，请重新输入");
            return null;
        }

        // 如果缓存为空，则从服务层查询所有部门信息并缓存
        if (cache == null) {
            // 调用服务层获取部门列表
            Result result = DeptService.list();
            // 将查询到的部门数据缓存
            cache = (DeptVo[]) result.data;
        }

        // 在缓存中查找指定ID 的部门
        DeptVo dept = null;
        for (DeptVo item : cache) {
            if (item.id == id) {
                // 找到对应ID的部门，输出部门信息
                System.out.println("该ID对应的数据是：");
                System.out.printf("ID：%d，名称：%s，电话：%s\n",item.id,item.name, item.phone);
                dept = item;
                break;
            }
        }

        // 如果未找到部门，则提示用户
        if (dept == null) {
            System.err.println("当前没有该ID对应的数据");
            return null;
        }

        return dept;
    }
}

